#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<queue>


typedef void (*Handler)(int data);

class QueueData{
  public:
    QueueData(){

    }
    QueueData(int data,Handler haneler){
      data_=data;
      handler_=haneler;
    }
    ~QueueData(){

    }
    void Run(){
      handler_(data_);
    }
  private:
    int data_;
    Handler handler_;

};
class QueueSafe{
  public:
    QueueSafe(){

      capacity=1;
      pthread_mutex_init(&lock_,NULL);
      pthread_cond_init(&cons_cond,NULL);
      pthread_cond_init(&prod_cond,NULL);
    }
    ~QueueSafe(){
      pthread_mutex_destroy(&lock_);
      pthread_cond_destroy(&cons_cond);
      pthread_cond_destroy(&prod_cond);
    }
    void Push(QueueData& data,int flag_){
      pthread_mutex_lock(&lock_);
      if(flag_==1){
        return;
      }
      while(que_.size()>=capacity){
        pthread_cond_wait(&prod_cond,&lock_);
      }
      que_.push(data);
      pthread_mutex_unlock(&lock_);
      pthread_cond_signal(&cons_cond);
    }
    void Pop(QueueData* data,int flag_){
      pthread_mutex_lock(&lock_);
      while(que_.empty()){
        if(flag_==1){
          pthread_mutex_unlock(&lock_);
          pthread_exit(NULL);
        }
        pthread_cond_wait(&cons_cond,&lock_);
      }
      *data=que_.front();
      que_.pop();
      pthread_mutex_unlock(&lock_);
      pthread_cond_signal(&prod_cond);
    }
    void Broadcast(){
      pthread_cond_broadcast(&cons_cond);
    }
  private:
    std::queue<QueueData> que_;
    int capacity;
    pthread_mutex_t lock_;
    pthread_cond_t cons_cond;
    pthread_cond_t prod_cond;
};
class ThreadPool{
  public:
    ThreadPool(){

    }
    ~ThreadPool(){
      if(sq_!=NULL){
        delete sq_;
      }
    }
    int InitThreadPool(int thread_count){
      flag_=0;
      sq_=new QueueSafe;
      if(sq_==NULL){
        return -1;
      }
      //0代表运行 1代表停止 flag是控制优雅退出函数的参数
      thread_count=thread_count;
      for(int i=0;i<thread_count;i++){
        pthread_t tid;
        int ret =pthread_create(&tid,NULL,workstart,(void*)this);
        if(ret<0){
          thread_count--;
          continue;
        }
      }
      if(thread_count<=0){
        return -1;
      }
      return 0;
    }
    void Push(QueueData&qd){
      sq_->Push(qd,flag_);

    }

    static void* workstart(void* arg){
      pthread_detach(pthread_self());
      ThreadPool* tp=(ThreadPool*)arg;
      while(1){
        QueueData qd;
        tp->sq_->Pop(&qd,tp->flag_);

        qd.Run();
      } 
    }

    void pthread_pool_exit(){
      flag_=1;
      sq_->Broadcast();
    }
  private:
    QueueSafe* sq_;
    int thread_count;

    int flag_;
};
void del1(int data){
  printf("i am deli,%d\n",data);
}


int main(){
  //QueueData sq(1,del1);
  // sq.Run();
  ThreadPool tp;
  int ret =tp.InitThreadPool(2);
  if(ret<0){
    return 0;
  }
  for(int i=0;i<100;i++){
    QueueData qd(i,del1);
    tp.Push(qd);
  }
  tp.pthread_pool_exit();
  while(1){

    sleep(1);
  }
  return 0;
}
